Skip to content

test: add Detox e2e suite with a dedicated E2ETestApp - #3881

Merged
isekovanic merged 19 commits into
developfrom
alexeyalterpesotskiy/rn-449-e2e-infra
Oct 28, 2026
Merged

isekovanic merged 19 commits into
developfrom
alexeyalterpesotskiy/rn-449-e2e-infra

Conversation

@testableapple

@testableapple testableapple commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

🎯 Goal

E2E test automation for the SDK, on par with the native iOS/Android and Flutter suites, running on PRs.

Linear: RN-450, RN-451, RN-452, RN-453, RN-454, RN-455, RN-457 (parent RN-449)

πŸ›  Implementation details

Dedicated app: examples/E2ETestApp. A new bare RN 0.88 workspace with only the SDK and its required peer dependencies (no Firebase, maps, video or navigation library), like the native SDKs' StreamChatUITestsApp. It has three screens: a user selector, the channel list, and a channel stacked over the list. It reads a MOCK_SERVER_URL launch argument (react-native-launch-arguments), never persists a login and runs without offline storage, so every test starts clean. A clean Release build takes ~2 min on an M-series Mac; the SampleApp took ~15 min on Android. The SampleApp app is unchanged; only its Fastfile gains the e2e lanes.

Framework (RN-450): Detox 20 + Jest 30 in examples/E2ETestApp/e2e/, with ios.sim.*, android.emu.* and android.att.* configs (debug and release).

Mock server (RN-451): the shared stream-chat-test-mock-server, one server per test through its driver (port 4569).

Page objects (RN-452) and robots (RN-453, RN-454, RN-455): structure and naming follow the native suites:

  • BackendRobot / ParticipantRobot: 1:1 ports of the Android robots
  • UserRobot + UserRobot*Asserts: assert extensions, like Android's
  • LoginPage / ChannelListPage / MessageListPage
  • setUpStreamTestCase(), step(), and uiautomator-style element helpers

Robots chain fluently like the native ones: await userRobot.login().openChannel().assertMessage('Hi').

Smoke suite: 6 tests (MessageList Γ—3, ChannelList Γ—3), named after their Android counterparts and keeping the native expectations.

SDK (additive testIDs only): channel-preview-title, channel-preview-message, channel-preview-sender, and message-status-{read,delivered,sending,sent}, with a unit test.

CI (RN-457): .github/workflows/e2e-test.yml.

  • Android runs on PRs: ubuntu-latest, KVM, API 36 AOSP emulator, pixel profile (the native Android SDK's setup).
  • iOS runs only on demand (workflow_dispatch with ios: true), not on PRs, to save CI time and macOS runners: macos-15, Xcode 26.2, iPhone 17 Pro.
  • Gated like the iOS SDK: a cheap Check E2E Required job runs is_check_required over the e2e sources (Fastfile impact_analysis), and test_e2e checks it too.
  • Test E2E Result is the check to require in branch protection. It covers Android (it doesn't wait for iOS) and passes when the Android job passes or is skipped as not required.
  • Caching:
    • the built .app / .apk, keyed on the app and SDK sources but not on e2e/, so a test-only change skips the native build
    • node_modules of yarn workspaces focus e2etestapp
    • CocoaPods, ccache (with CCACHE_BINARY exported, without which RN's ccache wrappers silently skip ccache), the Detox framework, Gradle (cache-read-only: false, since setup-gradle otherwise only writes on the default branch), and the mock server's gems
    • each PR fills its own caches (the workflow doesn't run on develop): its first run builds cold, and later pushes reuse them
  • On failure, uploads the mock server logs, Detox's logs and screenshots, and the emulator's crash data.

Fastlane (in examples/SampleApp/fastlane, next to the repo's other lanes): start_mock_server, stop_mock_server, e2e_pod_install, test_e2e, e2e_check_required.

Notable findings, documented in examples/E2ETestApp/e2e/README.md:

  • Fabric mounts some testID'd views (message-list-item-*, message-text-container) empty, with their content as siblings, so page objects scope to message-content-wrapper or the list instead.
  • iOS runs without Detox's idle synchronization, which can wedge on RN's UIManager shadow queue. Robots wait explicitly, and taps retry while the target isn't hittable yet.
  • launchApp({ permissions }) makes Detox restart SpringBoard once per permission on every launch. On CI that cost 1.5–3 min per test, so the suite doesn't pass any.
  • Android sets the composer text directly (as the native suite does). Typing through Gboard left the text in a composing state that the composer didn't send.

How to run and extend the suite: examples/E2ETestApp/e2e/README.md.

🎨 UI Changes

None (testIDs only).

πŸ§ͺ Testing

Not covered yet: Allure TestOps reporting, full suite ports, and iOS on PRs (manual runs only, to save CI time and macOS runners).

β˜‘οΈ Checklist

  • I have signed the Stream CLA (required)
  • PR targets the develop branch
  • Documentation is updated
  • New code is tested in main example apps, including all possible scenarios
    • SampleApp iOS and Android
    • Expo iOS and Android

@testableapple
testableapple marked this pull request as ready for review October 20, 2026 18:09
@testableapple testableapple changed the title feat(SampleApp): add Detox e2e suite with mock server, robots and page objects test: add Detox e2e suite with a dedicated E2ETestApp Oct 20, 2026
@isekovanic
isekovanic self-requested a review October 26, 2026 10:00
Comment thread examples/SampleApp/fastlane/Fastfile Resolved
Comment thread .github/workflows/e2e-test.yml Resolved
A testID on the container View makes it non-collapsible, so view flattening
can't remove it. The SVG icons are native views anyway.
@Stream-SDK-Bot

Copy link
Copy Markdown
Contributor

SDK Size

title develop branch diff status
js_bundle_size 2036 KB 2036 KB +252 B 🟒
ai_components_size 163 KB 163 KB 0 B 🟒

@isekovanic
isekovanic merged commit 14850a3 into develop Oct 28, 2026
13 checks passed
@isekovanic
isekovanic deleted the alexeyalterpesotskiy/rn-449-e2e-infra branch October 28, 2026 16:21
@stream-ci-bot

Copy link
Copy Markdown
Contributor

πŸŽ‰ This PR is included in version 9.11.0 πŸŽ‰

The release is available on:

Your semantic-release bot πŸ“¦πŸš€

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants